package util.thread.threadpool;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author 李栋
 * @version 1.0.0
 * @className ThreadPooTest.java
 * @createTime 2021年06月13日 20:13:00
 */
public class ThreadPooTest {

    private static final Logger logger = LoggerFactory.getLogger(ThreadPooTest.class);

    private static final long THREAD_TIME_OUT = 60;

    @Test
    public void test() {
        // Cpu 核数
        int cpuNum = Runtime.getRuntime().availableProcessors();
        // 最大数
        int maxSize = 2 * cpuNum + 1;

        /**
         * 拒绝策略：当阻塞队列和最大线程都用完之后
         *
         * AbortPolicy：ThreadPoolExecutor中默认的拒绝策略就是AbortPolicy。直接抛出异常。
         * CallerRunsPolicy：在任务被拒绝添加后，会调用当前线程池的所在的线程去执行被拒绝的任务。
         * DiscardPolicy：会让被线程池拒绝的任务直接抛弃，不会抛异常也不会执行。
         * DiscardOldestPolicy：当任务呗拒绝添加时，会抛弃任务队列中最旧的任务也就是最先加入队列的，再把这个新任务添加进去。
         */
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(cpuNum,
                maxSize,
                THREAD_TIME_OUT,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(20),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        poolExecutor.execute(new Thread(() -> logger.info(Thread.currentThread().toString())));

    }

    @Test
    public void test1() {
        // Cpu 核数
        int cpuNum = Runtime.getRuntime().availableProcessors();
        // 核心线程数：线程池中默认可用的线程数
        int coreSize = cpuNum;
        // 最大线程数：当阻塞队列中放满之后，使用最大线程数中的线程
        int maxSize = 2 * coreSize + 1;

        // 有界的阻塞队列
        ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(20);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();

        // 当没有可用的线程的时候，在来任务则执行策略
        ThreadPoolExecutor.AbortPolicy abortPolicy = new ThreadPoolExecutor.AbortPolicy();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(coreSize,
                maxSize,
                THREAD_TIME_OUT,
                TimeUnit.SECONDS,
                arrayBlockingQueue,
                threadFactory,
                abortPolicy
        );
    }

    /**
     * 线程池的正确使用方式
     */
    @Test
    public void test2() {
        // 核心线程数
        int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
        // 最大线程数
        int maxPoolSize = Runtime.getRuntime().availableProcessors() << 1;
        // 当线程空闲时，保持活跃的时间 1000 毫秒 1s
        int keepAliveTime = 1000;
        // 阻塞队列大小
        int blockQueueSize = 1000;

        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,
                maxPoolSize,
                keepAliveTime,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(blockQueueSize),
                new ThreadPoolExecutor.AbortPolicy());

        threadPool.execute(() -> {
            logger.info("自定义线程池的使用...");
        });
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            logger.error("Error occur:", e);
        }
    }
}
